#include "SceneFbx.h"
#include "Shader.h"
#include "MeshFbx.h"
CSceneFbx::CSceneFbx(void)
:m_pFbxManager(NULL)
,m_pFbxScene(NULL)
{
}

CSceneFbx::~CSceneFbx(void)
{
	if ( m_pFbxManager )
	{
		DestroySdkObjects( m_pFbxManager );
	}
}

bool CSceneFbx::InitScene( const char * fileName )
{
	if ( !LoadSceneFbx( fileName ) )
	{
		printf("load scene fbx error\n");
		return false;
	}
	return true;
}

void CSceneFbx::DesdroyScene()
{

}

bool CSceneFbx::LoadSceneFbx( const char * fileName )
{
	bool bRet = false;
	if ( m_pFbxManager == NULL )
	{
		InitializeSdkObjects( m_pFbxManager, m_pFbxScene );
	}	
	
	// Get fbxScene by fbxImporter
	if( !LoadScene( m_pFbxManager, m_pFbxScene, fileName ))
	{
		printf("Load Fbx Scene Error!\n");
		return false;
	}
	// Do prepare job  
	// Axis system translate base on our need
	KFbxAxisSystem FbxAxisSystem = m_pFbxScene->GetGlobalSettings().GetAxisSystem();
	KFbxAxisSystem SceneAxisSystem( KFbxAxisSystem::eOpenGL );

	if ( FbxAxisSystem != SceneAxisSystem )
	{
		SceneAxisSystem.ConvertScene( m_pFbxScene );
	}

	// get the unit and translate 
	KFbxSystemUnit SystemUnit = m_pFbxScene->GetGlobalSettings().GetSystemUnit();
	if ( SystemUnit.GetScaleFactor() != 1.0 )
	{
		KFbxSystemUnit::cm.ConvertScene( m_pFbxScene );
	}

	m_pFbxScene->FillAnimStackNameArray( m_AnimStackNameArray );
	
	FillCameraArray( m_pFbxScene, m_CameraArray );

	// translate the nurbs and mesh nurb_surface
	TriangulateRecursive( m_pFbxScene->GetRootNode() );

	// bake the material and textures for the scene
	LoadCacheRecursive( m_pFbxScene->GetRootNode(), m_pAnimLayer );

	// Convert the fbx to the es data
	PreparePointCacheDate( m_pFbxScene );

	return true;
}

void CSceneFbx::DrawSceneFbx()
{
	UnLoadCacheRecursive();
}

void CSceneFbx::FillCameraArray( KFbxScene * pScene, KArrayTemplate< KFbxNode *> & CameraArray )
{
	CameraArray.Clear();
	FillCameraArrayRecursive( pScene->GetRootNode(), CameraArray );
}

void CSceneFbx::FillCameraArrayRecursive( KFbxNode * pNode, KArrayTemplate< KFbxNode * > & CameraArray )
{
	if ( pNode != NULL )
	{
		if ( pNode->GetNodeAttribute() )
		{
			if ( pNode->GetNodeAttribute()->GetAttributeType() == KFbxNodeAttribute::eCAMERA )
			{
				CameraArray.Add( pNode );
			}
		}

		for ( int i = 0 ; i < pNode->GetChildCount(); ++i )
		{
			FillCameraArrayRecursive( pNode, CameraArray );
		}
	}
}

void CSceneFbx::FillPoseArray( KFbxScene * pScene, KArrayTemplate< KFbxPose *> & PoseArray )
{
	const int nCount = pScene->GetPoseCount();
	for ( int i = 0; i < nCount; ++i )
	{
		PoseArray.Add( pScene->GetPose(i) );
	}
}

void CSceneFbx::PreparePointCacheDate( KFbxScene * pScene )
{
	
}
// load the file and create the texture 
void CSceneFbx::LoadTextureFromFile( const KString & pFilePath, unsigned int & nTextureObject )
{

}
// translate the mesh and nurb and so on to the triangle 
void CSceneFbx::TriangulateRecursive( KFbxNode *pNode )
{
	if ( pNode != NULL )
	{
		KFbxNodeAttribute * Attibute = pNode->GetNodeAttribute(); 
		if ( Attibute )
		{
			if ( Attibute->GetAttributeType() == KFbxNodeAttribute::eNURB ||
				Attibute->GetAttributeType() == KFbxNodeAttribute::eMESH ||
				Attibute->GetAttributeType() == KFbxNodeAttribute::eNURBS_SURFACE ||
				Attibute->GetAttributeType() == KFbxNodeAttribute::ePATCH )
			{
				KFbxGeometryConverter Converter( pNode->GetFbxSdkManager() );
				Converter.TriangulateInPlace( pNode );
			}
		}

		int iChildCount = pNode->GetChildCount();
		for ( int i = 0; i < iChildCount; ++i )
		{
			TriangulateRecursive( pNode );
		}
	}
}
// kfb loader all kinds of data
void CSceneFbx::LoadCacheRecursive( KFbxNode * pNode, KFbxAnimLayer * pAnimLayer )
{
	if ( pNode == NULL )
		return;
	KFbxNodeAttribute *pNodeAttribute = pNode->GetNodeAttribute();
	if ( pNodeAttribute )
	{
		// add mesh
		if ( pNodeAttribute->GetAttributeType() == KFbxNodeAttribute::eMESH )
		{
			CMeshFbx *pMesh = new CMeshFbx();
			KFbxMesh *pFbxMesh = pNode->GetMesh();
			if ( pMesh->Initialize( pFbxMesh ) )
			{
				m_pMeshList.push_back( pMesh );
			}
			else
			{
				delete pMesh;
				pMesh = NULL;
			}
		}
		// add light
		if ( pNodeAttribute->GetAttributeType() == KFbxNodeAttribute::eLIGHT )
		{

		}

		// add 
		if ( pNodeAttribute->GetAttributeType() == KFbxNodeAttribute::eNURB )
		{

		}
	}

	for ( int i = 0; i < pNode->GetChildCount(); ++i )
	{
		LoadCacheRecursive( pNode->GetChild( i ), pAnimLayer );
	}
}

void CSceneFbx::UnLoadCacheRecursive( KFbxNode * pNode )
{
	MESHFBXLIST::const_iterator it = m_pMeshList.begin();
	for ( ; it != m_pMeshList.end(); ++it )
	{
		delete (*it); 
	}
	m_pMeshList.clear();
}

void CSceneFbx::LoadCacheRecursive( KFbxScene *pScene, KFbxAnimLayer * pAnimlayer, const char * pFbxFileName )
{

}

void CSceneFbx::UnLoadCacheRecursive( KFbxScene * pScene )
{

}